package com.vast.metrix.viewer.bustraffic.viewers;

import java.awt.Color;
import java.awt.Font;
import java.text.DecimalFormat;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYAreaRenderer;
import org.jfree.chart.renderer.xy.XYAreaRenderer;
import org.jfree.chart.util.RelativeDateFormat;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.xy.TableXYDataset;
import com.vast.metrix.jfreechart.chart.swt.VaSTChartFrame;
import com.vast.metrix.viewer.bustraffic.models.BusTraffic;

public class BusTrafficViewer {
	private JFreeChart              chart;
	private static VaSTChartFrame   frame;
	private String                  chartTitle;
	private BusTrafficPlotter[]     busTrafficPlotterArray;
	private String[]                busNames;
	private boolean               isMaximumItemAge_ms = false;
	private boolean               isAutoRange = false;
	private int                   samplingRate_ms  = 100;
	private int                   maximumItemAge_ms   = 500;
	
	public BusTrafficViewer(Composite parent, String chartTitle) {	
		//this.scrolPanel = new ScrolledComposite (parent, SWT.V_SCROLL | SWT.H_SCROLL);
		//this.panel = new Composite(scrolPanel, SWT.NONE);
		this.chartTitle = chartTitle;
		TimeTableXYDataset defaultDataset = new TimeTableXYDataset();
		
		this.chart = ChartFactory.createStackedXYAreaChart(
				this.chartTitle,              // chart title
	            "Time",                           // domain axis label
	            "Byte",                           // range axis label
	            (TableXYDataset) defaultDataset,  // data
	            PlotOrientation.VERTICAL,         // the plot orientation
	            false,                            // legend
	            false,                            // tooltips
	            false                             // urls
	     );
	     XYPlot plot = (XYPlot) chart.getPlot();
	     StackedXYAreaRenderer renderer = new StackedXYAreaRenderer(XYAreaRenderer.AREA_AND_SHAPES);
	        renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
	        plot.setRenderer(0, renderer);
	        plot.setDomainCrosshairVisible(false);
	        plot.setRangeCrosshairVisible(false);
	        plot.setBackgroundPaint(Color.black);
	        plot.setDomainGridlinePaint(Color.green);
	        plot.setRangeGridlinePaint(Color.green);
		
		this.frame             = new VaSTChartFrame(parent, SWT.NONE, chart, true);
		//this.frame.setSize(640, 480);
		//scrolPanel.setContent(panel);
		//panel.setSize(panel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
	}
	
	public void createChart(String[] graphNames, int samplingRate_ms) {
		createChart(graphNames, samplingRate_ms, this.maximumItemAge_ms, this.isMaximumItemAge_ms, this.isAutoRange);
	}
		
	public void createChart(String[] graphNames, int samplingRate_ms, int maximumItemAge_ms) {
		createChart(graphNames, samplingRate_ms, maximumItemAge_ms, true, this.isAutoRange);
	}
	
	public void createChart(String[] graphNames, int samplingRate_ms, int maximumItemAge_ms, boolean isMaximumItemAge_ms, boolean isAutoRange) {
		this.busNames = graphNames;
		this.isMaximumItemAge_ms = isMaximumItemAge_ms;
		this.isAutoRange = isAutoRange;
		this.samplingRate_ms = samplingRate_ms;
		this.maximumItemAge_ms = maximumItemAge_ms;
		
		/*
		 * Define domainAxis (X-Axis) as DateAxis
		 */
		DateAxis domainAxis = new DateAxis("Time");

		RelativeDateFormat rdf = new RelativeDateFormat(0);
		rdf.setLenient(true);
		rdf.setDaySuffix("d");
		rdf.setHourSuffix("h");
		rdf.setMinuteSuffix("m");
		rdf.setSecondSuffix("s");
        rdf.setSecondFormatter(new DecimalFormat("00.000"));
        
        domainAxis.setDateFormatOverride(rdf);
		domainAxis.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12));
		domainAxis.setLabelFont(new Font("SansSerif", Font.PLAIN, 12));
		domainAxis.setLowerMargin(0.0);
		domainAxis.setUpperMargin(0.0);
		domainAxis.setTickLabelsVisible(true);
		domainAxis.setAutoRange(true);
		
		/*
		 * Define Root Plot (CombinedDomainXYPlot)
		 */
	    CombinedDomainXYPlot plot = new CombinedDomainXYPlot(domainAxis);
	    plot.setBackgroundPaint(Color.lightGray);
		plot.setDomainGridlinePaint(Color.white);
		plot.setRangeGridlinePaint(Color.white);
		
		this.busTrafficPlotterArray    = new BusTrafficPlotter[busNames.length];
		for (int i = 0; i < this.busNames.length; i++ ) {
			this.busTrafficPlotterArray[i] = new BusTrafficPlotter(this.busNames[i], 1000.0, 1000.0, 1000.0, this.samplingRate_ms, this.maximumItemAge_ms, this.isMaximumItemAge_ms, this.isAutoRange);
			plot.add(this.busTrafficPlotterArray[i].getSubPlot());
		}

		JFreeChart chart = new JFreeChart(this.chartTitle, new Font("SansSerif", Font.BOLD, 12), plot, false);
		chart.setBackgroundPaint(Color.white);	
		
		this.frame.setChart(chart);
		update();

		/*
		timeSeriesUpdater = new TimeSeriesUpdater(sequence, frame.getDisplay(), this.busTrafficPlotterArray[0].getTransferByteSeries(), refreshRate_ms);
		Executor ex = Executors.newSingleThreadExecutor();
		ex.execute(timeSeriesUpdater);
		*/
		/*
		final Runnable chartUpater = new Runnable() {
			public synchronized void run() {
			// TODO Auto-generated method stub
			
			if (!display.isDisposed() && sequence.isReceiveConnection() && isChartUpdate()) {
				display.asyncExec(new Runnable() {
					public void run() {
						for(int i = 0; i < busNames.length; i++) {
							BusTraffic maximumValue = busTrafficCollectionArray[i].getMaximumValue();
							busTrafficPlotterArray[i].UpdateUpperValueOfRangeAxis(maximumValue.transferByte, maximumValue.latency + maximumValue.utilization);
							busTrafficPlotterArray[i].getTransferByteSeries().fireSeriesChanged();
						}
					}
				});
			}
			
			if (!display.isDisposed() && sequence.isReceiveConnection()) {
				try {
					wait(refreshRate_ms);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				display.asyncExec(this);
			}
		}};
		Executor ex = Executors.newSingleThreadExecutor();
		ex.execute(chartUpater);
		*/
	}
		
	public void fireSeriesChanged() {
		frame.getDisplay().asyncExec(new Runnable() {
			public void run() {
				for (int i = 0; i < busTrafficPlotterArray.length; i++) {
					busTrafficPlotterArray[i].fireSeriesChanged();
				}
			}
		});	
	}
	
	public void restoreAutoBounds() {
		frame.getDisplay().asyncExec(new Runnable() {
			public void run() {
				frame.restoreAutoDomainBounds();
				frame.restoreAutoRangeBounds();
			}
		});	
	}
	
	public void setTextTitleForDisplay(int subPlotIndex, double x, int itemIndex) {	
		busTrafficPlotterArray[subPlotIndex].setSubInformation(x, itemIndex);
	}
	
	public void updateUpperValueOfRangeAxis(final int index, final BusTraffic maximumValue, boolean isSynchronized) {
		if(isSynchronized) {
			frame.getDisplay().asyncExec(new Runnable() {
				public void run() {
					busTrafficPlotterArray[index].UpdateUpperValueOfRangeAxis(maximumValue.transferByte, maximumValue.activity, maximumValue.latency + maximumValue.utilization);
				}
			});
		} else {
			busTrafficPlotterArray[index].UpdateUpperValueOfRangeAxis(maximumValue.transferByte, maximumValue.activity, maximumValue.latency + maximumValue.utilization);
		}
	}
	public void addBusTraffic(int busIndex, long currentTime_ms, double transferByte, double activity, double latency, double utilization, boolean isSynchronized) {
		busTrafficPlotterArray[busIndex].addBusTraffic(currentTime_ms, transferByte, activity, latency, utilization, isSynchronized);
	}
	
	public void addBusTraffic(int busIndex, long currentTime_ms, double transferByte, double activity, double latency, double utilization) {
		busTrafficPlotterArray[busIndex].addBusTraffic(currentTime_ms, transferByte, activity, latency, utilization);
	}
	
	public static void update() {
		frame.getDisplay().asyncExec(new Runnable() {
			public void run() {
				frame.forceRedraw();
			}
		});	
	}
	
	public TimeSeries[] getRefreshTrigger() {
		TimeSeries[] refreshTriggers = new TimeSeries[this.busTrafficPlotterArray.length];
		for (int i = 0; i < this.busTrafficPlotterArray.length; i++) {
			refreshTriggers[i] = this.busTrafficPlotterArray[i].getTransferByteSeries();
		}
		return refreshTriggers;
	}
	
}
